package $2_2coreclasses;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class FnBigDecimal {

    public static void main(String[] args) {
        // BigDecimal 表示一个任意大小且精度完全准确的浮点数。
        BigDecimal bd = new BigDecimal("123.4567");
        System.out.println(bd.multiply(bd)); // 15241.55677489
        
        // BigDecimal用scale()表示小数位数
        BigDecimal d1 = new BigDecimal("123.45");
        BigDecimal d2 = new BigDecimal("123.4500");
        BigDecimal d3 = new BigDecimal("1234500");
        System.out.println(d1.scale()); // 2,两位小数
        System.out.println(d2.scale()); // 4
        System.out.println(d3.scale()); // 0
        
        // 通过BigDecimal的stripTrailingZeros()方法，可以将一个BigDecimal格式化为一个相等的，但去掉了末尾0的BigDecimal：
        BigDecimal d4 = new BigDecimal("123.4500");
        BigDecimal d5 = d4.stripTrailingZeros();
        System.out.println(d4.scale()); // 4
        System.out.println(d5.scale()); // 2,因为去掉了00

        BigDecimal d6 = new BigDecimal("1234500");
        BigDecimal d7 = d6.stripTrailingZeros();
        System.out.println(d6.scale()); // 0
        System.out.println(d7.scale()); // -2
        // 如果一个BigDecimal的scale()返回负数，例如，-2，表示这个数是个整数，并且末尾有2个0。
        
        // 可以对一个BigDecimal设置它的scale，如果精度比原始值低，那么按照指定的方法进行四舍五入或者直接截断
        BigDecimal d8 = new BigDecimal("123.456789");
        BigDecimal d9 = d8.setScale(4, RoundingMode.HALF_UP); // 四舍五入，123.4568
        BigDecimal d10 = d8.setScale(4, RoundingMode.DOWN); // 直接截断，123.4567
        System.out.println(d9);
        System.out.println(d10);
        
        // 对BigDecimal做加、减、乘时，精度不会丢失，但是做除法时，存在无法除尽的情况，这时，就必须指定精度以及如何进行截断
        BigDecimal d11 = new BigDecimal("123.456");
        BigDecimal d12 = new BigDecimal("23.456789");
        BigDecimal d13 = d11.divide(d12, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入
        BigDecimal d14 = d11.divide(d12, 8, RoundingMode.DOWN); // 报错：ArithmeticException，因为除不尽
        System.out.println(d13);
        System.out.println(d14);
        
        // 还可以对BigDecimal做除法的同时求余数
        BigDecimal n = new BigDecimal("99");
        BigDecimal m = new BigDecimal("8");
        BigDecimal[] dr = n.divideAndRemainder(m);
        // 商
        System.out.println(dr[0]); // 12
        // 余数
        System.out.println(dr[1]); // 3
        // 可以利用这个方法判断两个BigDecimal是否是整数倍数
        if (dr[1].signum() == 0) {
            // n是m的整数倍
            System.out.println("n是m的整数倍。");
        }else {
            // n不是m的整数倍
            System.out.println("n不是m的整数倍。");
        }
        
        // 在比较两个BigDecimal的值是否相等时，要特别注意，使用equals()方法不但要求两个BigDecimal的值相等，还要求它们的scale()相等
        BigDecimal d15 = new BigDecimal("123.456");
        BigDecimal d16 = new BigDecimal("123.45600");
        System.out.println(d15.equals(d16)); // false,因为scale不同
        System.out.println(d15.equals(d16.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2
        System.out.println(d15.compareTo(d16)); // 0
        // 必须使用compareTo()方法来比较，它根据两个值的大小分别返回负数、正数和0，分别表示小于、大于和等于。
        // 总是使用compareTo()比较两个BigDecimal的值，不要使用equals()！ 
        
        /*
         * 小结
         * BigDecimal用于表示精确的小数，常用于财务计算；
         * 比较BigDecimal的值是否相等，必须使用compareTo()而不能使用equals()。
         * */
    }

}
